﻿#include <vector>

using namespace std;

/** Типы предметов в ручье (Item Type) */
#define IT_STONE   0; /**< камень */
#define IT_PLUG    1; /**< пробка */
#define IT_BOTTLE  2; /**< бутылка */
#define IT_BRANCH  3; /**< ветка */
#define IT_LEAF    4; /**< лист */
#define IT_CAN     5; /**< банка */
#define IT_WIRE    6; /**< проволока */
#define IT_LOG     7; /**< бревно */
#define IT_MAX     8; /**< кол-во типов предметов */
// сталкер мод - шприц, гильза, аптечка, противогаз, чаечный ключ, книга +++

/** "Константы" ошибок (Error Result) */
#define ER_OK    0; /**< нет ошибки */
#define ER_ERROR 1; /**< ошибка */

/**
@brief Класс, определяющий предмет в ручье
*/
class TItem
{
    public:
        //! Поля
        int type;         /**< Тип предмета (IT_*) */
        bool isMoveable; /**< Признак продвижности предмета */
        bool isVisible;  /**< Признак нахождения предмета в кадре */
        int speed;       /**< Скорость движения */
        int x;           /**< Координата X объекта */
        int y;             /**< Координата Y объекта */
        int picture;     /**< Cсылка на изображение (id ресурса ???) */ //+++
        int width;       /**< Ширина предмета */
        int height;      /**< Высота предмета */
        int damage;      /**< Урон, наносимый предметом, при столкновении */
        //! Методы
        TItem();         /**< Конструктор */
        ~TItem();        /**< Деструктор */
};

/**
@brief Класс, определяющий часть ручья, видимую на экране
*/
class TVisible
{
    public:
        //! Поля
        int width;   /**< Ширина экрана (по умолчанию - 800) */
        int height;  /**< Высота экрана (по умолчанию - 480) */
        int up;      /**< Верхняя координата (по умолчанию - height) */
        int down;    /**< Нижняя координата (по умолчанию - 0) */
        bool isCreekCyclic; /**< Признак цикличности ручья (по умолчанию - false) */
        //! Методы
        TVisible();  /**< Конструктор */
        ~TVisible(); /**< Деструктор */
        int moveFrameUp(int delta);   /**< Сдвинуть кадр вверх по ручью */
        int moveFrameDown(int delta); /**< Сдвинуть кадр вниз по ручью */
};

/**
@brief Структура, описывающая координату точки (x,y)
*/
struct TXY {
  int x;
  int y;
};

/**
@brief Структура, описывающая координату точки (x,y) и производную в ней (p)
*/
struct TXYP {
  int x;
  int y;
  float p;
};

/**
@brief Структура, описывающая 2D-четырехугольник
*/
struct TRectangle {
  TXY v1;
  TXY v2;
  TXY v3;
  TXY v4;
  TXY c; /* Центр четырехугольника*/
};

/**
@brief Класс, определяющий весь ручей
*/
class TCreek
{
    public:
        //! Поля
        vector <TXYP> leftBank;                 /**< Левый берег ручья (каркас) */
        vector <TXYP> rightBank;                /**< Правый берег ручья (каркас) */
        vector <TXY> leftPixelBank;             /**< Левый берег (точки) */
        vector <TXY> rightPixelBank;            /**< Правый берег (точки) */
        vector <TRectangle> leftRectangleBank;  /**< Левый берег (четырехугольники) */
        vector <TRectangle> rightRectangleBank; /**< Правый берег (четырехугольники) */
        TVisible frame;           /**< Кадр, определяющий видимую на экране часть ручья */
        vector<TItem> itemsUnderWater; /**< Вектор предметов в ручье под водой */
        vector<TItem> itemsOnWater;    /**< Вектор предметов в ручье на воде */
        vector<TItem> itemsOverWater;  /**< Вектор предметов в ручье над водой */
        //! Поля, которые надо при необходимости заполнить перед вызовом fillBankCurves() или generateCreek()
        int creekLength;          /**< Длина ручья в пикселях (по умолчанию - 10 000) */
        int itemsCountUnderWater; /**< Число предметов под водой (по умолчанию - creekLength/1000) */
        int itemsCountOnWater;    /**< Число предметов в воде (по умолчанию - creekLength/1000) */
        int itemsCountOverWater;  /**< Число предметов над водой (по умолчанию - creekLength/1000) */
        int screenWidth;          /**< Ширина экрана в пикселях (по умолчанию - 800) */
        int xLeftBegin;           /**< Начальное положение левого берега (по умолчанию - screenWidth/4) */
        int xRightBegin;          /**< Начальное положение левого берега (по умолчанию - screenWidth*3/4) */
        int bankStep;             /**< Расстояние между поворотами ручья в пикселях (по умолчанию - screenWidth/20)*/
        int minCreekWidth;        /**< Минимальная ширина ручья в пикселях (по умолчанию - screenWidth/4) */
        int maxCreekWidth;        /**< Максимальная ширина ручья в пикселях (по умолчанию - screenWidth*3/4)*/
        bool isCreekCyclic;       /**< Признак цикличности ручья (по умолчанию - false) */
        int delta;                /**< Шаг интерполяции берега (по умолчанию - 5) */
        //! Методы
        TCreek();                   /**< Конструктор */
        ~TCreek();                  /**< Деструктор */
        void buildBankCurves();        /**< Создание каркасных точек, описывающих берега */
        void fillBankCurves( int from, int to ); /**< Попикселное построение берегов */
        int getCreekWidth( int y ); /**< Получить ширину ручья по указанной координате */
        int getLeftBank( int y );   /**< Получить положение левого берега по указанной координате */
        int getRightBank( int y );  /**< Получить положение правого берега по указанной координате */
        void checkVisibleItems();   /**< Проверка видимости предметов в ручье */
        void placeItems();          /**< Начальное расположение предметов в ручье */
        void generateCreek();        /**< Процедура генерации ручья */
};
